package cn.lili.modules.permission.serviceimpl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.SearchVO;
import cn.lili.modules.permission.entity.dos.Menu;
import cn.lili.modules.permission.entity.dos.Role;
import cn.lili.modules.permission.entity.dos.RoleMenu;
import cn.lili.modules.permission.entity.dos.StoreUser;
import cn.lili.modules.permission.entity.dto.MenuSearchParams;
import cn.lili.modules.permission.entity.vo.MenuVO;
import cn.lili.modules.permission.mapper.MenuMapper;
import cn.lili.modules.permission.service.MenuService;
import cn.lili.modules.permission.service.RoleMenuService;
import cn.lili.modules.permission.service.RoleService;
import cn.lili.modules.permission.service.StoreUserService;
import cn.lili.mybatis.util.PageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.*;

/**
 * 权限业务层实现
 *
 * @author Chopper
 * @since 2020/11/17 3:49 下午
 */
@Slf4j
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
	/**
	 * 菜单角色
	 */
	@Autowired
	private RoleMenuService roleMenuService;

	@Autowired
	private Cache<List<Menu>> cache;
	@Autowired
	private StoreUserService storeUserService;
	@Autowired
	private MenuService menuService;
	@Autowired
	private RoleService roleService;

	@Override
	public void deleteIds(List<String> ids) {
		QueryWrapper<RoleMenu> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("menu_id", ids);
		// 如果已有角色绑定菜单，则不能直接删除
		if (roleMenuService.count(queryWrapper) > 0) {
			throw new ServiceException(ResultCode.PERMISSION_MENU_ROLE_ERROR);
		}
		this.removeByIds(ids);
	}

	@Override
	public List<MenuVO> findUserTree(String state) {
		AuthUser authUser = Objects.requireNonNull(UserContext.getCurrentUser());
		// 商家进入
		if (StringUtils.isNotEmpty(state) && state.equals("1")) { // 0平台 1商家
			StoreUser byId = storeUserService.getById(authUser.getId());
			List<RoleMenu> byRoleId = roleMenuService.findByRoleId(byId.getRoleIds());
			if (byRoleId.size() == 0) {
				return this.tree(new ArrayList<Menu>());
			}
			List<String> list = new ArrayList();
			byRoleId.forEach(item -> {
				list.add(item.getMenuId());
			});
			List<Menu> userMenus = menuService.list(new LambdaQueryWrapper<Menu>().in(Menu::getId, list));
			return this.tree(userMenus);
		}
		// 平台超级管理员进入
		if (Boolean.TRUE.equals(authUser.getIsSuper())) {
			return this.tree(state);
		}
		// 平台普通管理员进入
		List<Menu> userMenus = this.baseMapper.findByUserId(authUser.getId());
		return this.tree(userMenus);
	}

	@Override
	public List<Menu> findUserList(String userId) {
		String cacheKey = CachePrefix.MENU_USER_ID.getPrefix() + userId;
		List<Menu> menuList = cache.get(cacheKey);
		if (menuList == null) {
			menuList = this.baseMapper.findByUserId(userId);
			cache.put(cacheKey, menuList);
		}
		return menuList;
	}

	/**
	 * 添加更新菜单
	 *
	 * @param menu
	 *            菜单数据
	 * @return 是否成功
	 */
	@Override
	public boolean saveOrUpdateMenu(Menu menu) {
		if (CharSequenceUtil.isNotEmpty(menu.getId())) {
			cache.vagueDel(CachePrefix.MENU_USER_ID.getPrefix());
			cache.vagueDel(CachePrefix.USER_MENU.getPrefix());
		}
		return this.saveOrUpdate(menu);
	}

	@Override
	public List<Menu> findByRoleIds(String roleId) {
		QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("role_id", roleId);
		return this.list(queryWrapper);
	}

	@Override
	public List<Menu> searchList(MenuSearchParams menuSearchParams) {
		// title 需要特殊处理
		String title = null;
		if (CharSequenceUtil.isNotEmpty(menuSearchParams.getTitle())) {
			title = menuSearchParams.getTitle();
			menuSearchParams.setTitle(null);
		}
		QueryWrapper<Menu> queryWrapper = PageUtil.initWrapper(menuSearchParams, new SearchVO());
		if (CharSequenceUtil.isNotEmpty(title)) {
			queryWrapper.like("title", title);
		}
		queryWrapper.orderByDesc("sort_order");
		return this.baseMapper.selectList(queryWrapper);
	}

	@Override
	public List<MenuVO> tree(String state) {
		try {
			QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
			if (state.equals("1")) { // state 0平台 1商家
				queryWrapper.eq("state", "1");
			} else {
				queryWrapper.eq("state", "0");
			}
			List<Menu> menus = baseMapper.selectList(queryWrapper);
			return tree(menus);
		} catch (Exception e) {
			log.error("菜单树错误", e);
		}
		return Collections.emptyList();
	}

	/**
	 * 传入自定义菜单集合
	 *
	 * @param menus
	 *            自定义菜单集合
	 * @return 修改后的自定义菜单集合
	 */
	private List<MenuVO> tree(List<Menu> menus) {
		List<MenuVO> tree = new ArrayList<>();
		menus.forEach(item -> {
			if (item.getLevel() == 0) {
				MenuVO treeItem = new MenuVO(item);
				initChild(treeItem, menus);
				tree.add(treeItem);
			}
		});
		// 对一级菜单排序
		tree.sort(Comparator.comparing(Menu::getSortOrder));
		return tree;
	}

	/**
	 * 递归初始化子树
	 *
	 * @param tree
	 *            树结构
	 * @param menus
	 *            数据库对象集合
	 */
	private void initChild(MenuVO tree, List<Menu> menus) {
		if (menus == null) {
			return;
		}
		menus.stream().filter(item -> (item.getParentId().equals(tree.getId()))).forEach(child -> {
			MenuVO childTree = new MenuVO(child);
			initChild(childTree, menus);
			tree.getChildren().add(childTree);
		});
	}

	/**
	 * 根据parentId查看所绑定的菜单权限
	 *
	 * @param menuSearchParams
	 * @return
	 */
	@Override
	public List<MenuVO> treeJurisdiction(MenuSearchParams menuSearchParams) {
		try {
			// 如果为0则代表第一级，第一级默认带所有数据权限
			QueryWrapper queryWrapper = new QueryWrapper();
			if (StringUtils.isNotEmpty(menuSearchParams.getState()) && menuSearchParams.getState().equals("1")) {
				queryWrapper.eq("state", '1'); // 1商家
			} else {
				queryWrapper.eq("state", '0'); // 0平台
			}
			if (!menuSearchParams.getParentId().equals("0")) { // 是否为顶级
				List<RoleMenu> byRoleId = roleMenuService.findByRoleId(menuSearchParams.getParentId()); // 根据上级角色Id查询他所拥有的菜单权限
				List list = new ArrayList();
				byRoleId.forEach(item -> {
					list.add(item.getMenuId()); // 菜单Id
				});
				queryWrapper.in("id", list); // 查找上级所勾选的数据权限
			}
			List menus = this.baseMapper.selectList(queryWrapper);
			return tree(menus);
		} catch (Exception e) {
			log.error("菜单树错误", e);
		}
		return Collections.emptyList();
	}

	@Override
	public void updatememberMenu() {
		List<StoreUser> list = storeUserService
				.list(new QueryWrapper<StoreUser>().eq("delete_flag", 0).eq("parent_id", 0));
		list.forEach(item -> {
			String roleIds = item.getRoleIds();
			// 删除角色关联菜单
			roleMenuService.deleteRoleMenu(roleIds);
			// 跟新角色关联菜单
			this.roleMenu(roleService.getById(roleIds));
		});
	}

	/**
	 * 创建角色管理的菜单
	 */
	private void roleMenu(Role role) {
		QueryWrapper<Menu> objectQueryWrapper = new QueryWrapper<>();
		objectQueryWrapper.eq("state", "1");
		List<Menu> list = menuService.list(objectQueryWrapper);
		list.forEach(item -> {
			RoleMenu roleMenu = new RoleMenu();
			roleMenu.setRoleId(role.getId()); // 角色Id
			roleMenu.setMenuId(item.getId());// 菜单Id
			roleMenu.setCreateBy(UserContext.getCurrentUser().getUsername());
			roleMenu.setCreateTime(new Date());
			roleMenuService.save(roleMenu);
		});
	}
}
